package com.aic.aicdetactor;

import java.io.UnsupportedEncodingException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.List;

import android.Manifest;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.bluetooth.BluetoothManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;

import com.aic.aicdetactor.analysis.CurveValuePair;
import com.aic.aicdetactor.analysis.FFTValuePair;
import com.aic.aicdetactor.analysis.ReceivedDataAnalysis;
import com.aic.aicdetactor.broadcast.Keys;
import com.aic.aicdetactor.common.CommonDef;
import com.aic.aicdetactor.common.Constants;
import com.aic.aicdetactor.common.Setting;
import com.aic.aicdetactor.crash.AICApplication;
import com.aic.aicdetactor.service.BroadcastService;
import com.aic.aicdetactor.util.HexUtil;
import com.aic.aicdetactor.util.LogUtil;
import com.aic.aicdetactor.util.SystemUtil;
import com.aic.aicdetactor.util.ToastUtil;
import com.aic.xj.app.ble.BluetoothRequest;
import com.aic.xj.app.resource.GBMap;
import com.aic.xj.app.sdk.HandlerConstants;
import com.aic.xj.app.sdk.Sensor;
import com.aic.xj.app.sdk.SensorOperator;
import com.aic.xj.app.util.StringUtil;
import com.aicmonitor.aicdetactorsimple.R;
import com.viewpagerindicator.TabPageIndicator;
import com.aic.xj.data.aicdataanalysis.FreDomainPara;

public class MainActivity extends FragmentActivity {
    public static final String[] PAGE = new String[]{"控制", "状态值", "曲线图", "日志", "设置"};
    private TabPageIndicatorAdapter _tabAdapter = null;
    private ReceivedDataAnalysis _analysis = null;

    private Object _lock = new Object();
    private DataRequestThread _requestor = null;
    private SensorOperator _operator = null;

    private ProgressDialog _waitingDialog = null;
    private String _bluetoothAddress;
    private float mEmissivity = 0.98f;//发射率
    private static String TAG = "MainActivity";
    private int mTimeStartSum = 15000;//2016-11-09 liuhg添加
    private int mTimeConnectOut = 8000;//2016-11-09 liuhg添加
    private Setting setting = null;//2016-11-15 liuhg添加
    private String mMaxSamplerate = "2560";
    private int mSamplerate = 0;
    private int mSamplepoint = 0;

    private Intent intent; //2019-2-16 chupengyu添加,负责启动接收广播服务的intent

    private ControlReceiver controlReceiver;

//	private final static String START = "com.aicmonitor.aicdetactorsimple.control.start";
//	private final static String STOP = "com.aicmonitor.aicdetactorsimple.control.stop";

    private final static String TOTAL = "com.aicmonitor.aicdetactorsimple.control";
    private final static String SEND_BLUETOOTH_VALUE = "com.aicmonitor.aicdetactorsimple.control.getBluetoothList";

    private int REQUEST_ENABLE_BT = 11;

    private static String[] PERMISSIONS_STORAGE = {
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.ACCESS_COARSE_LOCATION};

    /*
        校验蓝牙权限
        */
    private void checkBluetoothPermission() {
        if (Build.VERSION.SDK_INT >= 23) {
            //校验是否已具有模糊定位权限
            if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED || ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                ActivityCompat.requestPermissions(MainActivity.this, PERMISSIONS_STORAGE, REQUEST_ENABLE_BT);
            } else {//权限已打开
                ToastUtil.showToast(this, "蓝牙权限已打开");
            }
        } else {//小于23版本直接使用
            ToastUtil.showToast(this, "API小于23版本直接使用");
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if (requestCode == REQUEST_ENABLE_BT) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {//蓝牙权限开启成功
                ToastUtil.showToast(this, "蓝牙权限已打开");
//				startScan();
            } else {
                ToastUtil.showToast(MainActivity.this, "蓝牙权限未开启,请设置");
            }
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //检查权限
        checkBluetoothPermission();
        //注册广播
        controlReceiver = new ControlReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(TOTAL);
        //当网络发生变化的时候，系统广播会发出值为android.net.conn.CONNECTIVITY_CHANGE这样的一条广播
        registerReceiver(controlReceiver, intentFilter);

        this.setTitle(R.string.app_title);

        try {
            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_AvailableSensor, new ArrayAdapter<String>(getBaseContext(), android.R.layout.simple_list_item_single_choice, new ArrayList<String>()));
            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Log, new CustomListAdapter(getBaseContext(), R.layout.custom_list, new ArrayList<String>()));

            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Temperature, CommonDef.InvalidValue);//2016-11-08 liuhg添加
            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Voltage, CommonDef.InvalidValue);//2016-11-08 liuhg添加
            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Sensor_Name_Address, "");//2016-11-07 liuhg添加

            _tabAdapter = new TabPageIndicatorAdapter(getSupportFragmentManager());
            ViewPager pager = (ViewPager) findViewById(R.id.viewpager);
            pager.setAdapter(_tabAdapter);

            TabPageIndicator indicator = (TabPageIndicator) findViewById(R.id.tabpageindicator);
            indicator.setViewPager(pager);

            indicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

                @Override
                public void onPageSelected(int arg0) {
                }

                @Override
                public void onPageScrolled(int arg0, float arg1, int arg2) {
                }

                @Override
                public void onPageScrollStateChanged(int arg0) {

                }
            });

            setting = new Setting();//此处实例化是为了在开启程序时在SD卡中建立默认文件夹
            _operator = new SensorOperator(_handler, getApplicationContext());

        } catch (Exception e) {
            LogUtil.GetInstance().append(e);
            btn_exit_Event(null);
        }

        String isInit = getIntent().getStringExtra("init");
        if (!TextUtils.isEmpty(isInit) && isInit.equals("init")) {
            btn_hide_Event(null);
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        String isInit = getIntent().getStringExtra("init");
        if (!TextUtils.isEmpty(isInit) && isInit.equals("init")) {
            btn_hide_Event(null);
        } else {
            btn_hide_Event(null);
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        btn_hide_Event(null);
    }

    public class ControlReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
//	    	Toast.makeText(MainActivity.this,action,Toast.LENGTH_SHORT).show();
            switch (action) {
                case TOTAL:
                    boolean isSearchStart = intent.getBooleanExtra("isSearchStart", false);//是否开始搜索
                    boolean isSearchStop = intent.getBooleanExtra("isSearchStop", false);//是否停止搜索
                    boolean isStart = intent.getBooleanExtra("isStart", false);//是否开始采集数据
                    boolean isStop = intent.getBooleanExtra("isStop", false);//是否停止采集数据
                    boolean isChangeName = intent.getBooleanExtra("isChangeName", false);//是否改名
                    boolean isExit = intent.getBooleanExtra("isExit", false);//是否退出
                    boolean isHide = intent.getBooleanExtra("isHide", false);//是否隐藏
                    boolean isOpen = intent.getBooleanExtra("isOpen", false);//是否打开
                    boolean IsTipsShow = intent.getBooleanExtra("IsTipsShow", false);//提示是否打开
                    boolean IsTipsHide = intent.getBooleanExtra("IsTipsHide", false);//提示是否关闭

                    if (isSearchStart) {
                        synchronized (_lock) {
                            if (_requestor != null) {
                                ToastUtil.showToast(getBaseContext(), "正在测量，无法搜索传感器，请先停止测量");
                                return;
                            }
                        }
                        if (!_operator.isDiscovering()) {
                            ListView lv = (ListView) findViewById(R.id.lv_sensor);
                            ((ArrayAdapter<String>) lv.getAdapter()).clear();
                            _operator.startDiscovery(15000);
                        } else {
                        }
                    } else if (isSearchStop) {
                        _operator.stopDiscovery();
                    } else if (isStart) {
                        String sensorname = intent.getStringExtra("name");
                        if (TextUtils.isEmpty(sensorname)) {
                            ToastUtil.showToast(getBaseContext(), "没携带蓝牙名称");
                            return;
                        }

                        String address = sensorname.substring(sensorname.indexOf("[") + 1, sensorname.indexOf("]"));
                        _bluetoothAddress = address;
                        List<BluetoothRequest> requests = makeRequests();
                        int interval = 0;

                        float defaulta = 0;
                        float defaultv = 0;
                        float defaultd = 0;
                        float defaultt = 0;
                        float defaulte = 0;
                        EditText txt_default_A = (EditText) findViewById(R.id.txt_default_A);
                        EditText txt_default_V = (EditText) findViewById(R.id.txt_default_V);
                        EditText txt_default_D = (EditText) findViewById(R.id.txt_default_D);
                        EditText txt_default_T = (EditText) findViewById(R.id.txt_default_T);
                        EditText txt_default_E = (EditText) findViewById(R.id.txt_default_E);
                        try {
                            defaulte = Float.parseFloat(txt_default_E.getText().toString());
                            defaulta = Float.parseFloat(txt_default_A.getText().toString());
                            defaultv = Float.parseFloat(txt_default_V.getText().toString());
                            defaultd = Float.parseFloat(txt_default_D.getText().toString());
                            defaultt = Float.parseFloat(txt_default_T.getText().toString());
                            if (defaulte < 0.7f || defaulte > 1f) {
                                ToastUtil.showToast(getBaseContext(), "无效数值，发射率范围为0.7~1.0");
                                return;
                            }
                            SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
                            SharedPreferences.Editor editor = mSharedPreferences.edit();
                            editor.putFloat(CacheControl.Key_Value_Txt_Default_E, defaulte);
                            editor.commit();
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Txt_Default_E, defaulte);
                        } catch (Exception ex) {
//							txt_default_E.setTextColor(Color.RED);
                            txt_default_A.setTextColor(Color.RED);
                            txt_default_V.setTextColor(Color.RED);
                            txt_default_D.setTextColor(Color.RED);
                            txt_default_T.setTextColor(Color.RED);
                            ToastUtil.showToast(getBaseContext(), "五个分析初始值不正确，请正确填写五个浮点数");
                            return;
                        }
                        if (ReceivedDataAnalysis.saveSensorPrams(_bluetoothAddress, defaulta, defaultv, defaultd, defaultt)) {
//							txt_default_E.setTextColor(Color.BLACK);
                            txt_default_A.setTextColor(Color.BLACK);
                            txt_default_V.setTextColor(Color.BLACK);
                            txt_default_D.setTextColor(Color.BLACK);
                            txt_default_T.setTextColor(Color.BLACK);
                        } else {
//							txt_default_E.setTextColor(Color.RED);
                            txt_default_A.setTextColor(Color.RED);
                            txt_default_V.setTextColor(Color.RED);
                            txt_default_D.setTextColor(Color.RED);
                            txt_default_T.setTextColor(Color.RED);
                        }
                        _analysis = new ReceivedDataAnalysis(defaulta, defaultv, defaultd, defaultt);
                        _analysis.InputTempPrams(address, 0);
                        _requestor = new DataRequestThread(_operator, address, requests, interval);
                        _waitingDialog = ProgressDialog.show(MainActivity.this, "开始测量", "开始中，请稍后…");
                        _waitingDialog.setCancelable(true);
                        boolean flag = false;
                        try {
                            flag = (Boolean) CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration);
                        } catch (Exception e) {
                            // TODO: handle exception
                            flag = false;
                        }
                        if (flag) {
                            mTimeStartSum = 6000;
                            mTimeConnectOut = 3000;
                        }
                        new Thread() {
                            @Override
                            public void run() {
//								if (_requestor.init(15000)) //2016-11-09 liuhg修改前原程序
                                if (_requestor.init(mTimeStartSum, mTimeConnectOut))//2016-11-09 liuhg修改
                                {
                                    _requestor.start();
                                    _handler.obtainMessage(Constants.HANDLER_MEASUREMENT_STARTED, 1, 0, null).sendToTarget();
                                } else {
                                    if (_requestor != null) {
                                        _requestor.cancel();
                                        _requestor = null;
                                    }
                                    _handler.obtainMessage(Constants.HANDLER_MEASUREMENT_STARTED, 0, 0, null).sendToTarget();
                                }
                            }
                        }.start();
                    } else if (isStop) {
                        stopBluetoothMeasurment("停止中", "正在停止，请稍后……", "已停止测量，可以重新设定参数再次开始测量", 0);
                    } else if (isChangeName) {
                        String sensorname = intent.getStringExtra("name");
                        final String address = sensorname.substring(sensorname.lastIndexOf("[") + 1, sensorname.lastIndexOf("]"));
                        final String newname = intent.getStringExtra("newName");
                        final String encodingname = GBMap.getInstance().encoding(newname);
                        if (encodingname.equals("#ContentTooLong")) {
                            ToastUtil.showToast(getBaseContext(), "传感器名字不能为空");
                        } else if (encodingname.equals("#ContentTooLong")) {
                            ToastUtil.showToast(getBaseContext(), "传感器名字太长，9个汉字或15个英文字母");
                        } else if (encodingname.equals("#UnsupportChar")) {
                            ToastUtil.showToast(getBaseContext(), "仅支持汉字大写字母和#@()，请重取名");
                        } else {
                            _waitingDialog = ProgressDialog.show(MainActivity.this, "开始改名", "改名中，请稍后…");
                            _waitingDialog.setCancelable(true);
                            new Thread() {
                                @Override
                                public void run() {
                                    byte[] encodingnamebytes = null;
                                    try {
                                        encodingnamebytes = encodingname.getBytes("ASCII");
                                    } catch (UnsupportedEncodingException e1) {
                                        Log.e("zxh", e1.toString());
                                    }
                                    try {
                                        String result = _operator.open(address, 15000);
                                        if (result.equals("#OK")) {
                                            byte[] data = new byte[]{(byte) 0x7F, (byte) 0x17, (byte) 0xD4, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,};
                                            for (int i = 0; i < encodingnamebytes.length; i++) {
                                                data[i + 3] = encodingnamebytes[i];
                                            }
                                            byte[] response = _operator.ioControl(0xD4, data, 4000, 20);
                                            if (response != null && response[2] == (byte) 0xD4 && response[3] == (byte) 0x5A) {
                                                _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 1, 0, newname).sendToTarget();
                                            } else {
                                                _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 0, 0, newname).sendToTarget();
                                            }
                                        } else {
                                            _handler.obtainMessage(HandlerConstants.HANDLER_ERROR, 0, 0, "连接失败:" + result).sendToTarget();
                                        }

                                    } catch (Exception e) {
                                        _handler.obtainMessage(HandlerConstants.HANDLER_ERROR, 0, 0, e.getMessage()).sendToTarget();
                                        _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 0, 0, newname).sendToTarget();
                                    } finally {
                                        _operator.close();
                                    }
                                }
                            }.start();
                        }
                    } else if (isExit) {
                        synchronized (_lock) {
                            if (_requestor != null) {
                                _requestor.cancel();
                                _requestor = null;
                            }
                        }
                        android.os.Process.killProcess(android.os.Process.myPid());
                    } else if (isHide) {
                        btn_hide_Event(null);
                    } else if (isOpen) {
                        startActivity(new Intent(MainActivity.this, MainActivity.class));
                    } else if (IsTipsShow) {
                        Button button = (Button) findViewById(R.id.btn_tips);
                        AICApplication.isTips = true;
                        if (button != null)
                            button.setText("提示开");
                    } else if (IsTipsHide) {
                        Button button = (Button) findViewById(R.id.btn_tips);
                        AICApplication.isTips = false;
                        if (button != null)
                            button.setText("提示关");
                    }
                    break;
            }
        }
    }


//	@Override
//	protected void onStop() //2016-11-11 liuhg修改前原程序  修改后程序进入后台不会关闭
//	{
//		android.os.Process.killProcess(android.os.Process.myPid());
//	}

    public void btn_search_sensor_Event(View view) {
        synchronized (_lock) {
            if (_requestor != null) {
                ToastUtil.showToast(getBaseContext(), "正在测量，无法搜索传感器，请先停止测量");
                return;
            }
        }
        if (!_operator.isDiscovering()) {
            ListView lv = (ListView) findViewById(R.id.lv_sensor);
            ((ArrayAdapter<String>) lv.getAdapter()).clear();
            _operator.startDiscovery(15000);
        } else {
            _operator.stopDiscovery();
        }
    }

    public void btn_start_measurement_Event(View view) {
        synchronized (_lock) {
            if (_requestor == null) {
                _operator.stopDiscovery();
                //2019-2-16 chupengyu添加  启动广播服务接收数据 start
                intent = new Intent();
                intent.setClass(this, BroadcastService.class);
                startService(intent);
                //end
                ListView lv = (ListView) findViewById(R.id.lv_sensor);
                int index = lv.getCheckedItemPosition();
                if (index != -1) {
                    @SuppressWarnings("unchecked")
                    String sensorname = ((ArrayAdapter<String>) lv.getAdapter()).getItem(index);
                    if (sensorname != null) {
                        String address = sensorname.substring(sensorname.indexOf("[") + 1, sensorname.indexOf("]"));
                        _bluetoothAddress = address;
                        List<BluetoothRequest> requests = makeRequests();
                        int interval = 0;

                        float defaulta = 0;
                        float defaultv = 0;
                        float defaultd = 0;
                        float defaultt = 0;
                        float defaulte = 0;
                        EditText txt_default_A = (EditText) findViewById(R.id.txt_default_A);
                        EditText txt_default_V = (EditText) findViewById(R.id.txt_default_V);
                        EditText txt_default_D = (EditText) findViewById(R.id.txt_default_D);
                        EditText txt_default_T = (EditText) findViewById(R.id.txt_default_T);
                        EditText txt_default_E = (EditText) findViewById(R.id.txt_default_E);
                        try {
                            defaulte = Float.parseFloat(txt_default_E.getText().toString());
                            defaulta = Float.parseFloat(txt_default_A.getText().toString());
                            defaultv = Float.parseFloat(txt_default_V.getText().toString());
                            defaultd = Float.parseFloat(txt_default_D.getText().toString());
                            defaultt = Float.parseFloat(txt_default_T.getText().toString());
                            if (defaulte < 0.7f || defaulte > 1f) {
                                ToastUtil.showToast(getBaseContext(), "无效数值，发射率范围为0.7~1.0");
                                return;
                            }
                            SharedPreferences mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this.getBaseContext());
                            SharedPreferences.Editor editor = mSharedPreferences.edit();
                            editor.putFloat(CacheControl.Key_Value_Txt_Default_E, defaulte);
                            editor.commit();
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Txt_Default_E, defaulte);
                        } catch (Exception ex) {
//							txt_default_E.setTextColor(Color.RED);
                            txt_default_A.setTextColor(Color.RED);
                            txt_default_V.setTextColor(Color.RED);
                            txt_default_D.setTextColor(Color.RED);
                            txt_default_T.setTextColor(Color.RED);
                            ToastUtil.showToast(getBaseContext(), "五个分析初始值不正确，请正确填写五个浮点数");
                            return;
                        }
                        if (ReceivedDataAnalysis.saveSensorPrams(_bluetoothAddress, defaulta, defaultv, defaultd, defaultt)) {
//							txt_default_E.setTextColor(Color.BLACK);
                            txt_default_A.setTextColor(Color.BLACK);
                            txt_default_V.setTextColor(Color.BLACK);
                            txt_default_D.setTextColor(Color.BLACK);
                            txt_default_T.setTextColor(Color.BLACK);
                        } else {
//							txt_default_E.setTextColor(Color.RED);
                            txt_default_A.setTextColor(Color.RED);
                            txt_default_V.setTextColor(Color.RED);
                            txt_default_D.setTextColor(Color.RED);
                            txt_default_T.setTextColor(Color.RED);
                        }
                        _analysis = new ReceivedDataAnalysis(defaulta, defaultv, defaultd, defaultt);
                        _analysis.InputTempPrams(address, 0);
                        _requestor = new DataRequestThread(_operator, address, requests, interval);
                        _waitingDialog = ProgressDialog.show(MainActivity.this, "开始测量", "开始中，请稍后…");
                        _waitingDialog.setCancelable(true);
/**************************************************以下内容为2016-11-09 liuhg添加*************************************************/
                        boolean flag = false;
                        try {
                            flag = (Boolean) CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration);
                        } catch (Exception e) {
                            // TODO: handle exception
                            flag = false;
                        }
                        if (flag) {
                            mTimeStartSum = 6000;
                            mTimeConnectOut = 3000;
                        }
/**************************************************以上内容为2016-11-09 liuhg添加*************************************************/
                        new Thread() {
                            @Override
                            public void run() {
//								if (_requestor.init(15000)) //2016-11-09 liuhg修改前原程序
                                if (_requestor.init(mTimeStartSum, mTimeConnectOut))//2016-11-09 liuhg修改
                                {
                                    _requestor.start();
                                    _handler.obtainMessage(Constants.HANDLER_MEASUREMENT_STARTED, 1, 0, null).sendToTarget();
                                } else {
                                    if (_requestor != null) {
                                        _requestor.cancel();
                                        _requestor = null;
                                    }
                                    _handler.obtainMessage(Constants.HANDLER_MEASUREMENT_STARTED, 0, 0, null).sendToTarget();
                                }
                            }
                        }.start();
                    } else {
                        // new
                        // AlertDialog.Builder(this).setTitle("请先搜索并选择一个传感器");
                        ToastUtil.showToast(getBaseContext(), "请先搜索并选择一个传感器");
                    }
                } else {
                    // new
                    // AlertDialog.Builder(this).setTitle("请先搜索并选择一个传感器");
                    ToastUtil.showToast(getBaseContext(), "请先搜索并选择一个传感器");
                }
            } else {
                ToastUtil.showToast(getBaseContext(), "正在测量，无法开始，请先停止测量");
            }
        }
    }

    private void setControlStatus(boolean enable) {
        ListView lv = (ListView) findViewById(R.id.lv_sensor);
        if (lv != null) {
            lv.setEnabled(enable);
        }
        Spinner s = (Spinner) findViewById(R.id.spn_axistype);
        if (s != null) {
            s.setEnabled(enable);
        }
        s = (Spinner) findViewById(R.id.spn_datatype);
        if (s != null) {
            s.setEnabled(enable);
        }
        s = (Spinner) findViewById(R.id.spn_samplepoint);
        if (s != null) {
            s.setEnabled(enable);
        }
        s = (Spinner) findViewById(R.id.spn_samplerate);
        if (s != null) {
            s.setEnabled(enable);
        }

        EditText et = (EditText) findViewById(R.id.txt_default_A);
        if (et != null) {
            et.setEnabled(enable);
        }
        et = (EditText) findViewById(R.id.txt_default_D);
        if (et != null) {
            et.setEnabled(enable);
        }
        et = (EditText) findViewById(R.id.txt_default_T);
        if (et != null) {
            et.setEnabled(enable);
        }
        et = (EditText) findViewById(R.id.txt_default_V);
        if (et != null) {
            et.setEnabled(enable);
        }
    }

    private List<BluetoothRequest> makeRequests() {
        /**************************************************以下内容为2016-11-09 liuhg添加*************************************************/
        boolean flag = false;
        try {
            flag = (Boolean) CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration);
        } catch (Exception e) {
            // TODO: handle exception
            flag = false;
        }
/**************************************************以上内容为2016-11-09 liuhg添加*************************************************/
        List<BluetoothRequest> requests = new ArrayList<BluetoothRequest>();
        // D1
        byte[] data = new byte[]{(byte) 0x7F, (byte) 0x14, (byte) 0xD1, (byte) 0x01, (byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

        Spinner s = (Spinner) findViewById(R.id.spn_axistype);
        data[3] = (byte) (s.getSelectedItemPosition() + 1);
        s = (Spinner) findViewById(R.id.spn_datatype);
        data[4] = (byte) (s.getSelectedItemPosition() + 1);
        s = (Spinner) findViewById(R.id.spn_samplerate);
        short sr;
        mSamplerate = Integer.valueOf(s.getSelectedItem().toString());
        if (mSamplerate > Integer.valueOf(mMaxSamplerate)) {
            sr = Short.parseShort(mMaxSamplerate);
        } else {
            sr = Short.parseShort(s.getSelectedItem().toString());
        }
//		short sr = Short.parseShort(s.getSelectedItem().toString());
        data[5] = (byte) ((sr & 0xff00) >> 8);
        data[6] = (byte) (sr & 0xff);
        s = (Spinner) findViewById(R.id.spn_samplepoint);
        short sp = Short.parseShort(s.getSelectedItem().toString());
        mSamplepoint = sp;
        int totallen = 2 * sp + 40;
        data[7] = (byte) ((sp & 0xff00) >> 8);
        data[8] = (byte) (sp & 0xff);

        int timeout = Constants.EveryPackageDelay * (sp * 2 / Constants.EveryPackageLen) + (short) (1000.0 * (float) sp / (float) sr) + 6200;
        if (flag) {
            data = new byte[]{(byte) 0x7F, (byte) 0x14, (byte) 0xD6, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
            BluetoothRequest r = new BluetoothRequest(0xD6, data, 20, null, 4000);
            requests.add(r);
        } else {
            BluetoothRequest r = new BluetoothRequest(0xD1, data, totallen, null, timeout);
            requests.add(r);

            boolean flag_rpm = false;
            try {
                flag_rpm = (Boolean) CacheControl.GetInstance().get(CacheControl.Key_Enable_RPM);
            } catch (Exception e) {
                // TODO: handle exception
                flag_rpm = false;
            }
            if (flag_rpm) {
                data = new byte[]{(byte) 0x7F, (byte) 0x14, (byte) 0xD3, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

//				r = new BluetoothRequest(0xD3, data, 20, null, 4000);//2016-12-24 liuhg修改前原程序
                r = new BluetoothRequest(0xD3, data, 20, null, 10000);//2016-12-24 liuhg修改  最低转速时 超时设置延长到10s
                requests.add(r);
            }

            data = new byte[]{(byte) 0x7F, (byte) 0x14, (byte) 0xD6, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

            r = new BluetoothRequest(0xD6, data, 20, null, 4000);
            requests.add(r);

            data = new byte[]{(byte) 0x7F, (byte) 0x14, (byte) 0xD7, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};

            r = new BluetoothRequest(0xD7, data, 20, null, 4000);
            requests.add(r);
        }
        return requests;
    }

    public void btn_stop_measurement_Event(View view) {
        stopBluetoothMeasurment("停止中", "正在停止，请稍后……", "已停止测量，可以重新设定参数再次开始测量", 0);
    }

    public void btn_set_name_Event(View view) {
        synchronized (_lock) {
            if (_requestor != null) {
                ToastUtil.showToast(getBaseContext(), "正在测量，无法为传感器改名，请先停止测量");
                return;
            }

            ListView lv = (ListView) findViewById(R.id.lv_sensor);
            int index = lv.getCheckedItemPosition();
            if (index != -1) {
                @SuppressWarnings("unchecked")
                String sensorname = ((ArrayAdapter<String>) lv.getAdapter()).getItem(index);
                if (sensorname != null) {
                    final String address = sensorname.substring(sensorname.lastIndexOf("[") + 1, sensorname.lastIndexOf("]"));

                    final EditText edit = new EditText(this);
                    new AlertDialog.Builder(this).setTitle("请输入新名字").setCancelable(true).setIcon(android.R.drawable.ic_dialog_info).setView(edit).setPositiveButton("确定", new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialog, int which) {
                            final String newname = edit.getText().toString();
                            final String encodingname = GBMap.getInstance().encoding(newname);
                            if (encodingname.equals("#IsNullOrWhiteSpace")) {
                                ToastUtil.showToast(getBaseContext(), "传感器名字不能为空");
                            } else if (encodingname.equals("#ContentTooLong")) {
                                ToastUtil.showToast(getBaseContext(), "传感器名字太长，9个汉字或15个英文字母");
                            } else if (encodingname.equals("#UnsupportChar")) {
                                ToastUtil.showToast(getBaseContext(), "仅支持汉字大写字母和#@()，请重取名");
                            } else {
                                _waitingDialog = ProgressDialog.show(MainActivity.this, "开始改名", "改名中，请稍后…");
                                _waitingDialog.setCancelable(true);
                                new Thread() {
                                    @Override
                                    public void run() {
                                        byte[] encodingnamebytes = null;
                                        try {
                                            encodingnamebytes = encodingname.getBytes("ASCII");
                                        } catch (UnsupportedEncodingException e1) {
                                            Log.e("zxh", e1.toString());
                                        }
                                        try {
                                            String result = _operator.open(address, 15000);
                                            if (result.equals("#OK")) {
                                                byte[] data = new byte[]{(byte) 0x7F, (byte) 0x17, (byte) 0xD4, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,};
                                                for (int i = 0; i < encodingnamebytes.length; i++) {
                                                    data[i + 3] = encodingnamebytes[i];
                                                }
                                                byte[] response = _operator.ioControl(0xD4, data, 4000, 20);
                                                if (response != null && response[2] == (byte) 0xD4 && response[3] == (byte) 0x5A) {
                                                    _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 1, 0, newname).sendToTarget();
                                                } else {
                                                    _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 0, 0, newname).sendToTarget();
                                                }
                                            } else {
                                                _handler.obtainMessage(HandlerConstants.HANDLER_ERROR, 0, 0, "连接失败:" + result).sendToTarget();
                                            }

                                        } catch (Exception e) {
                                            _handler.obtainMessage(HandlerConstants.HANDLER_ERROR, 0, 0, e.getMessage()).sendToTarget();
                                            _handler.obtainMessage(Constants.HANDLER_IOCONTROL_SETNAME, 0, 0, newname).sendToTarget();
                                        } finally {
                                            _operator.close();
                                        }
                                    }
                                }.start();
                            }
                        }
                    }).setNegativeButton("取消", null).show();
                } else {
                    ToastUtil.showToast(getBaseContext(), "请先搜索并选择一个传感器");
                }
            } else {
                ToastUtil.showToast(getBaseContext(), "请先搜索并选择一个传感器");
            }
        }
//		synchronized (_lock) {
//			if (_requestor != null) {
//				_requestor.onPause();
//				ToastUtil.showToast(getBaseContext(), "暂停测量");
//			}
//		}
    }

    public void btn_exit_Event(View view) {
        synchronized (_lock) {
            if (_requestor != null) {
                _requestor.cancel();
                _requestor = null;
            }
        }

        android.os.Process.killProcess(android.os.Process.myPid());
//		String notice=getDiagnosticInfo(3000);
//		ToastUtil.showToast(getBaseContext(), notice, Toast.LENGTH_LONG);
    }

    public void btn_hide_Event(View view) {
        moveTaskToBack(true);//最小化到后台 luanchModel必须是standar

//		Intent home = new Intent(Intent.ACTION_MAIN);
//		home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
//		home.addCategory(Intent.CATEGORY_HOME);
//		startActivity(home);
    }

    /**
     * 判断软件是否存在
     */
    public static boolean isAvilible(Context context, String packageName) {
        try {
            context.getPackageManager().getPackageInfo(packageName, 0);
            return true;
        } catch (PackageManager.NameNotFoundException e) {
            return false;
        }
    }

    public void btn_tips_Event(View view) {
        Button button = (Button) view;
        if (AICApplication.isTips) {
            AICApplication.isTips = false;
            button.setText("提示关");
            ToastUtil.cancelToast();
        } else {
            AICApplication.isTips = true;
            button.setText("提示开");
        }
    }

    public void checkbox_state_change_Event(View view) {
        CheckBox cbox = (CheckBox) findViewById(R.id.cb_temperature_calibration);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration, cbox.isChecked());
        if (cbox.isChecked()) {
            refreshCalibrationNotice();
        }
        stopBluetoothMeasurment("提示", "校准模式切换中，请稍后……", "校准状态改变，已停止测量，可以重新设定参数再次开始测量", 0);

    }

    public void checkbox_print_state_change_Event(View view) {
        CheckBox cbox = (CheckBox) findViewById(R.id.cb_temperature_print);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Print, cbox.isChecked());
        ToastUtil.showToast(getBaseContext(), "切换环境温度日志输出状态成功");

    }

    public void checkbox_enable_rpm_Event(View view) {
        CheckBox cbox = (CheckBox) findViewById(R.id.cb_enable_rmp);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Enable_RPM, cbox.isChecked());
        stopBluetoothMeasurment("提示", "测转速状态切换中，请稍后……", "转速测量状态改变，已停止测量，可以重新设定参数再次开始测量", 0);
//		CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_RPM, 0);
//		restoreTextViewValue(R.id.txt_rpm, CacheControl.Key_Value_RPM);
    }

    public void temperature_calibration_write_Event(View view) {
        synchronized (_lock) {
//			stopBluetoothMeasurment("提示", "正在停止测量，准备写入校准参数，请稍后……", "停止成功，准备写入校准值",1);
            writeCalibrationFile();
        }
    }

    public void temperature_calibration_prev_Event(View view) {
        synchronized (_lock) {
            String sensorname = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
            if (StringUtil.isNullOrWhiteSpace(sensorname)) {
                ToastUtil.showToast(getBaseContext(), "尚未选中传感器");
                return;
            }
            int calibrationindex = Integer.parseInt(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Index)));//当前应校准的温度索引
            if (calibrationindex == ReceivedDataAnalysis.getCalibrationTotalPoints()) {
                calibrationindex--;
            }
            calibrationindex--;
            if (calibrationindex >= 0) {
                CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Point_Index, calibrationindex);
                refreshCalibrationNotice();
            } else {
                calibrationindex = 0;
                CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Point_Index, calibrationindex);
                refreshCalibrationNotice();
            }
            Log.e("TAG", "calibrationindex=" + calibrationindex);
        }
    }

    public void temperature_calibration_next_Event(View view) {
        synchronized (_lock) {
            String sensorname = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
            if (StringUtil.isNullOrWhiteSpace(sensorname)) {
                ToastUtil.showToast(getBaseContext(), "尚未选中传感器");
                return;
            }
            int calibrationindex = Integer.parseInt(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Index)));//当前应校准的温度索引
            calibrationindex++;
            if (calibrationindex <= ReceivedDataAnalysis.getCalibrationTotalPoints() - 1) {
                CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Point_Index, calibrationindex);
                refreshCalibrationNotice();
            } else {
                calibrationindex = ReceivedDataAnalysis.getCalibrationTotalPoints() - 1;
                CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Point_Index, calibrationindex);
                refreshCalibrationNotice();
            }
            Log.e("TAG", "calibrationindex=" + calibrationindex);
        }
    }

    public void temperature_calibration_check_Event(View view) {
        synchronized (_lock) {
            String sensorname = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
            if (StringUtil.isNullOrWhiteSpace(sensorname)) {
                ToastUtil.showToast(getBaseContext(), "请先选择传感器");
                return;
            }
//			Setting setting = new Setting();
            String path = setting.getData_Media_Director(CommonDef.FILE_TYPE_BaseSetting);
            String filename = sensorname.substring(sensorname.indexOf("[") + 1, sensorname.indexOf("]")).replace(":", "") + "-temp.txt";
            if (SystemUtil.isFileExist(path, filename)) {
                String curve = ReceivedDataAnalysis.getTemperatureCurve(filename);
                ReceivedDataAnalysis.judgeCalibrationCurve(_handler, curve);
            } else {
                ToastUtil.showToast(getBaseContext(), "未找到当前传感器的校准文件");
                return;
            }
        }
    }

    public void pasueBlurtoothMeasurment() {
        Log.e(TAG, "挂起蓝牙线程");
        if (_requestor != null) {
            _requestor.onPause();
        }
        _handler.obtainMessage(Constants.HANDLER_BLUETOOTH_PAUSED).sendToTarget();
    }

    public void resumeBluetoothMeasurment() {
        Log.d(TAG, "恢复蓝牙线程");
        if (_requestor != null) {
            _requestor.onResume();
        }
    }
//	public void stopBluetoothMeasurment()
//	{
//		synchronized (_lock) {
//			if (_requestor != null) {
//				_requestor.cancel();
//				_requestor = null;
//			}
//
//			CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Running_Status, true);
//			setControlStatus(true);
//			ToastUtil.showToast(getBaseContext(), notice);
//		}
//	}

    /**
     * @param title  进度条标题
     * @param cue    进度条内容
     * @param notice 停止成功之后给用户的提示
     * @param flag   =0,只停止测量；=1.停止测量之后，进行校准参数更新
     */
    public void stopBluetoothMeasurment(String title, String cue, final String notice, final int flag) {
        synchronized (_lock) {
            _waitingDialog = ProgressDialog.show(MainActivity.this, title, cue);
            _waitingDialog.setCancelable(true);
            try {
                new Thread() {
                    @Override
                    public void run() {
                        if (_requestor != null) {
                            _requestor.cancel();
                            _requestor = null;
                        }
                        _handler.obtainMessage(Constants.HANDLER_BLUETOOTH_MEASURE_STOP, 1, flag, notice).sendToTarget();
                    }
                }.start();
            } catch (Exception e) {
                // TODO: handle exception
                _handler.obtainMessage(Constants.HANDLER_BLUETOOTH_MEASURE_STOP, 0, flag, "stopBluetoothMeasurment出现异常:" + e.getMessage()).sendToTarget();
            }

        }
    }

    class TabPageIndicatorAdapter extends FragmentPagerAdapter {

        public int _position = 0;

        public TabPageIndicatorAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            _position = position;
            Fragment fragment = new PageControl();
            Bundle args = new Bundle();
            args.putString("arg", PAGE[position]);
            fragment.setArguments(args);

            return fragment;
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return PAGE[position % PAGE.length];
        }

        @Override
        public int getCount() {
            return PAGE.length;
        }
    }

    private void rewriteCurveCalibration() {
        _waitingDialog = ProgressDialog.show(MainActivity.this, "写入校准值", "请勿挪动传感器及更改黑体箱温度！更新校准值，请稍后…");
        _waitingDialog.setCancelable(true);
        new Thread() {
            @Override
            public void run() {
                try {
                    Log.e(TAG, "rewriteCurveCalibration");
                    String sensorname = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
                    String BLEAddress = sensorname.substring(sensorname.indexOf("[") + 1, sensorname.indexOf("]"));
                    String BLEMac = BLEAddress.replace(":", "");
                    String BLECurveName = BLEMac + "-temp.txt";

                    int calibrationindex = Integer.parseInt(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Index)));//当前应校准的温度索引
                    double xValue = Double.parseDouble(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Voltage)));//蓝牙实时测量到的温度值换算之前的电压值
                    double yValue = Double.parseDouble(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Value)));//当前应校准的温度
//					xValue=1107;//测试用
//					yValue=20;//测试用
                    String curve = ReceivedDataAnalysis.getTemperatureCurve(BLECurveName);//获取当前蓝牙对应的温度曲线内容，如果不存在，则获取默认文件的曲线内容
                    if (ReceivedDataAnalysis.getCalibrationTotalPoints() != (ReceivedDataAnalysis.getCurveTotalPoints(curve) - 1)) //目前校准时，有一个点是低于-20度的，只不过该点不用校准，因此不显示给用户看
                    {
                        //校准的基准曲线上的基准点数与校准标准点数不一致
                        _handler.obtainMessage(Constants.HANDLER_REWRITE_CALIBRATION_CURVE, 0, 0, "禁止写入校准数据:" + "应校准点数与当前设备已有校准曲线文件包含的点数不一致，请删除当前设备校准曲线文件或重设温度校准范围及步进值").sendToTarget();
                        return;
                    } else {
                        ReceivedDataAnalysis.UpdateCurve(getApplicationContext(), curve, xValue, yValue, calibrationindex, BLEMac);
                        _handler.obtainMessage(Constants.HANDLER_REWRITE_CALIBRATION_CURVE, 1, 0, "写入校准数据成功").sendToTarget();
                    }

                } catch (Exception e) {
                    // TODO: handle exception
                    _handler.obtainMessage(Constants.HANDLER_REWRITE_CALIBRATION_CURVE, 0, 0, "写入校准数据失败:" + e.getMessage()).sendToTarget();
                }

            }
        }.start();
    }

    private void refreshCalibrationNotice() {
        String noticerange = ReceivedDataAnalysis.getTempCalRange();
        String noticestep = ReceivedDataAnalysis.getTempCalStep();
        String noticeschedule = "";
        String pointvalue = "";
        String pointindex = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Index));
        String name = (String) CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address);
        if (StringUtil.isNullOrWhiteSpace(name)) {
            pointindex = "0";
        }
//		noticeschedule=pointindex+"/"+String.valueOf(ReceivedDataAnalysis.getCalibrationTotalPoints());
        if (Integer.parseInt(pointindex) == ReceivedDataAnalysis.getCalibrationTotalPoints()) {
            noticeschedule = pointindex + "/" + String.valueOf(ReceivedDataAnalysis.getCalibrationTotalPoints()) + CommonDef.TempuratureCalbFinish;
            pointvalue = String.valueOf(ReceivedDataAnalysis.getShouldCalPointsValue(Integer.parseInt(pointindex) - 1));
        } else {
            noticeschedule = pointindex + "/" + String.valueOf(ReceivedDataAnalysis.getCalibrationTotalPoints());
            pointvalue = String.valueOf(ReceivedDataAnalysis.getShouldCalPointsValue(Integer.parseInt(pointindex)));
        }
//		String pointvalue=String.valueOf(ReceivedDataAnalysis.getShouldCalPointsValue(Integer.parseInt(pointindex)));
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Schedule, noticeschedule);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Range, noticerange);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Step, noticestep);
        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Calibration_Point_Value, pointvalue);

        restoreTextViewValue(R.id.txt_calibration_bluetooth_info, CacheControl.Key_Sensor_Name_Address);
        restoreTextViewValue(R.id.txt_calibration_ranage, CacheControl.Key_Tempurature_Calibration_Range);
        restoreTextViewValue(R.id.txt_calibration_step, CacheControl.Key_Tempurature_Calibration_Step);
        restoreTextViewValue(R.id.txt_calibration_schedule, CacheControl.Key_Tempurature_Calibration_Schedule);
        restoreTextViewValue(R.id.txt_calibration, CacheControl.Key_Tempurature_Calibration_Point_Value);

    }

    private void restoreTextViewValue(int id, String key) {
        TextView tv = (TextView) findViewById(id);
        if (tv != null) {
            Object value = CacheControl.GetInstance().get(key);
            if (value != null) {
                tv.setText(String.valueOf(value));
            }
        }
    }

    private void writeCalibrationFile() {
        String sensorname = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
        if (StringUtil.isNullOrWhiteSpace(sensorname)) {
            _handler.obtainMessage(Constants.HANDLER_CALIBRATION_CURVE_ERROR, 0, 0, "请选中传感器，再校准温度曲线").sendToTarget();
            return;
        }
        int allowdifferencevalue = CommonDef.TempuratureAllowDifferenceValue;
        double measurementvalue = Double.parseDouble(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Value_Temperature)));//蓝牙实时测量到的温度值
        if ((int) measurementvalue == CommonDef.InvalidValue) {
            _handler.obtainMessage(Constants.HANDLER_CALIBRATION_CURVE_ERROR, 0, 0, "测量温度不准确，请确认是否已经开始测量").sendToTarget();
            return;
        }
        int calibrationvalue = Integer.parseInt(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Value)));//当前应校准的温度
        if (Math.abs(measurementvalue - calibrationvalue) > allowdifferencevalue)//如果测量值和应校准值相差比较大，可能是黑体箱温度与用户想校准的温度不是一个点，给用户一个提示，是否要强行校准
        {
            showForceCalibrationDialog();
        } else {
            rewriteCurveCalibration();
        }
    }

    private final Handler _handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            try {
                if (msg.what == Constants.HANDLER_IOCONTROL) {

                    if (msg.obj != null) {
                        if (msg.arg1 == 0xD1) {
                            float[] values = null;
                            float evalue = 0;
                            float highvalue = 0;
                            float highvalue2 = 0;
                            float[] fxs = null;
                            float[] fys = null;
                            FreDomainPara[] fdps = null;
                            String unit = null;

                            double slope = 0;
                            double kurtosis = 0;
                            double wavefactor = 0;
                            double peakfactor = 0;
                            double pulsefactor = 0;
                            double clearancefactor = 0;
                            double kurtosisfactor = 0;
                            DecimalFormat df = new DecimalFormat("#.0000");//保留两位小数
                            synchronized (_analysis) {
                                byte[] data = (byte[]) msg.obj;

                                int result = _analysis.getDataFromBLE(data, (byte) msg.arg1);
                                if (result == 0) {
                                    values = _analysis.getWaveFloatData(mSamplerate);
                                    evalue = _analysis.getValidValue(); //有效值
                                    highvalue = _analysis.getFabsMaxValue(); //峰值
                                    highvalue2 = _analysis.getFengFengValue(); //峰峰值
                                    //2019-02-16 chupengyu start 开启广播传输数据
                                    startSendBroadcast(Keys.EVALUE_ACTION, Keys.eKey, String.valueOf(evalue));
                                    startSendBroadcast(Keys.VIBPEAK_ACTION, Keys.peakKey, String.valueOf(highvalue));
                                    startSendBroadcast(Keys.VIB_PEAK2PEAK_ACTION, Keys.vibPeak2PeakKey, String.valueOf(highvalue2));
                                    //end
                                    slope = Double.parseDouble(df.format(_analysis.GetSlope()));
                                    kurtosis = Double.parseDouble(df.format(_analysis.GetKurtosis()));
                                    wavefactor = Double.parseDouble(df.format(_analysis.GetWaveFactor()));
                                    peakfactor = Double.parseDouble(df.format(_analysis.GetPeakFactor()));
                                    pulsefactor = Double.parseDouble(df.format(_analysis.GetPulseFactor()));
                                    clearancefactor = Double.parseDouble(df.format(_analysis.GetClearanceFactor()));
                                    kurtosisfactor = Double.parseDouble(df.format(_analysis.GetKurtosisFactor()));

                                    fxs = _analysis.getFFTDataArrayX();
                                    fys = _analysis.getFFTDataArrayY();
                                    fdps = _analysis.getMaxFD();
                                    if (data[5] == (byte) 0x01) {
                                        unit = "m/^s";
                                    } else if (data[5] == (byte) 0x02) {
                                        unit = "mm/s";
                                    } else if (data[5] == (byte) 0x03) {
                                        unit = "um";
                                    } else {
                                        unit = "?";
                                    }
                                } else {
                                    addReceiveErrorLog("0xD1", result);
                                    return;
                                }
                            }

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Effective, evalue);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_High, highvalue);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_HighHigh, highvalue2);

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Unit, unit);

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Amplitude1, fdps[0].M);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Amplitude2, fdps[1].M);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Amplitude3, fdps[2].M);

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Rate1, fdps[0].Fre);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Rate2, fdps[1].Fre);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Rate3, fdps[2].Fre);

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Slope, slope);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Kurtosis, kurtosis);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_WaveFactor, wavefactor);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_PeakFactor, peakfactor);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_PulseFactor, pulsefactor);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_ClearanceFactor, clearancefactor);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_KurtosisFactor, kurtosisfactor);

                            restoreTextViewValue(R.id.txt_effective_value, CacheControl.Key_Value_Effective);
                            restoreTextViewValue(R.id.txt_high_value, CacheControl.Key_Value_High);
                            restoreTextViewValue(R.id.txt_highhigh_value, CacheControl.Key_Value_HighHigh);

                            restoreTextViewValue(R.id.txt_effective_value_unit, CacheControl.Key_Value_Unit);
                            restoreTextViewValue(R.id.txt_high_value_unit, CacheControl.Key_Value_Unit);
                            restoreTextViewValue(R.id.txt_highhigh_value_unit, CacheControl.Key_Value_Unit);

                            restoreTextViewValue(R.id.txt_effective_value2, CacheControl.Key_Value_Effective);
                            restoreTextViewValue(R.id.txt_high_value2, CacheControl.Key_Value_High);
                            restoreTextViewValue(R.id.txt_highhigh_value2, CacheControl.Key_Value_HighHigh);

                            restoreTextViewValue(R.id.txt_slope, CacheControl.Key_Value_Slope);
                            restoreTextViewValue(R.id.txt_kurtosis, CacheControl.Key_Value_Kurtosis);
                            restoreTextViewValue(R.id.txt_wavefactor, CacheControl.Key_Value_WaveFactor);
                            restoreTextViewValue(R.id.txt_peakfactor, CacheControl.Key_Value_PeakFactor);
                            restoreTextViewValue(R.id.txt_pulsefactor, CacheControl.Key_Value_PulseFactor);
                            restoreTextViewValue(R.id.txt_clearancefactor, CacheControl.Key_Value_ClearanceFactor);
                            restoreTextViewValue(R.id.txt_kurtosisfactor, CacheControl.Key_Value_KurtosisFactor);

                            restoreTextViewValue(R.id.txt_amplitude1, CacheControl.Key_Value_Amplitude1);
                            restoreTextViewValue(R.id.txt_amplitude2, CacheControl.Key_Value_Amplitude2);
                            restoreTextViewValue(R.id.txt_amplitude3, CacheControl.Key_Value_Amplitude3);

                            restoreTextViewValue(R.id.txt_rate1, CacheControl.Key_Value_Rate1);
                            restoreTextViewValue(R.id.txt_rate2, CacheControl.Key_Value_Rate2);
                            restoreTextViewValue(R.id.txt_rate3, CacheControl.Key_Value_Rate3);

                            TextView tv = (TextView) findViewById(R.id.txt_time_unit);
                            if (tv != null) {
                                Object value = CacheControl.GetInstance().get(CacheControl.Key_Value_Unit);
                                if (value != null) {
                                    tv.setText("Y " + String.valueOf(value));
                                } else {
                                    tv.setText("Y");
                                }
                            }

                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Chart_Wave, values);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Chart_FFT, new FFTValuePair(fxs, fys));

                            synchronized (PageControl._lock) {
                                if (PageControl._timeChart != null) {
                                    PageControl._timeChart.changeData(values);
                                }
                                if (PageControl._rateChart != null) {
                                    PageControl._rateChart.changeData(fxs, fys);
                                }
                            }
//							addLog("完成振动测量");
                        } else if (msg.arg1 == 0xD3) {
                            byte[] data = (byte[]) msg.obj;
                            float rpm = 0;
                            synchronized (_analysis) {
                                int result = _analysis.getDataFromBLE(data, (byte) msg.arg1);
                                if (result == 0) {
                                    rpm = _analysis.getZhuanSu(); //转速
                                    //2019-02-16 chupengyu start
                                    startSendBroadcast(Keys.RPM_ACTION, Keys.rpmKey, String.valueOf(rpm));    //开启广播传输转速值
                                    //end

                                } else {
                                    addReceiveErrorLog("0xD3", result);
                                    return;
                                }
                            }
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_RPM, rpm);
                            restoreTextViewValue(R.id.txt_rpm, CacheControl.Key_Value_RPM);
//							addLog("完成转速测量");
                        } else if (msg.arg1 == 0xD6) {
                            byte[] data = (byte[]) msg.obj;
                            double temp = 0.0f;
                            double voltage = 0.0f;
                            DecimalFormat df = new DecimalFormat("#.00");//保留两位小数
                            synchronized (_analysis) {
//								mEmissivity=getmEmissivity((Float)CacheControl.GetInstance().get(CacheControl.Key_Value_Txt_Default_E));
                                mEmissivity = (Float) CacheControl.GetInstance().get(CacheControl.Key_Value_Txt_Default_E);
//								Log.e("MainActivity", "Emissivity="+mEmissivity);
                                int result = _analysis.getDataFromBLE(data, (byte) msg.arg1);
                                if (result == 0) {
//									temp = _analysis.getTemperature();
                                    voltage = _analysis.getTemperature(mEmissivity)[0];
//									temp = _analysis.getTemperature(mEmissivity)[1];
                                    temp = Double.parseDouble(df.format(_analysis.getTemperature(mEmissivity)[1])); //温度
                                    //2019-02-16 chupengyu start
                                    startSendBroadcast(Keys.TEMP_ACTION, Keys.tempKey, String.valueOf(temp));    //开始发送广播传输温度值
                                    //end
                                    if (temp >= 300 || temp <= -20) {
                                        ToastUtil.showToast(getBaseContext(), "超出传感器测量范围");
                                    }
                                } else {
                                    addReceiveErrorLog("0xD6", result);
                                    return;
                                }
                            }
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Tempurature_Voltage, voltage);
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Temperature, temp);
                            restoreTextViewValue(R.id.txt_temperature, CacheControl.Key_Value_Temperature);
                            restoreTextViewValue(R.id.txt_temperature_voltage, CacheControl.Key_Tempurature_Voltage);
//							addLog("温度");

                        } else if (msg.arg1 == 0xD7) {
                            byte[] data = (byte[]) msg.obj;
                            int value = HexUtil.getInt(data, 3);
                            double power = (double) value * 2 / (double) 1000;
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_Power, power);
//                            sendBroadcast(new Intent(Constants.COM_AICMONITOR_AICDETACTORSIMPLE_CONTROL_BLUETOOTH_POWER).putExtra("power", power+""));
                            restoreTextViewValue(R.id.txt_power, CacheControl.Key_Value_Power);
//							addLog("电量");
                        }
                    } else {
                        addLog("错误：请求数据超时(" + HexUtil.toHexString(new byte[]{(byte) msg.arg1}) + "),接收包数：" + String.valueOf(msg.arg2));
                    }

                } else if (msg.what == Constants.HANDLER_MEASUREMENT_STARTED) {
                    if (_waitingDialog != null) {
                        _waitingDialog.dismiss();
                    }
                    if (msg.arg1 == 1) {
                        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Running_Status, false);
                        setControlStatus(false);
                        ToastUtil.showToast(getBaseContext(), "开始成功，请滑动Tab页面查看数据");
                    } else {
                        ToastUtil.showToast(getBaseContext(), "开始失败，请选择正确的传感器设备");
                    }
                } else if (msg.what == Constants.HANDLER_IOCONTROL_SETNAME) {
                    BluetoothManager bm = (BluetoothManager) getBaseContext().getSystemService(Context.BLUETOOTH_SERVICE);
                    if (bm != null) {
                        bm.getAdapter().disable();
                    }
                    if (_waitingDialog != null) {
                        _waitingDialog.dismiss();
                    }
                    if (msg.arg1 == 1) {
                        ToastUtil.showToast(getBaseContext(), "设置名称成功");
                        addLog("信息：设置名称成功：" + (String) msg.obj);
                    } else {
                        ToastUtil.showToast(getBaseContext(), "设置名称失败");
                        addLog("错误：设置名称失败：" + (String) msg.obj);
                    }
                    if (bm != null) {
                        bm.getAdapter().enable();
                    }
                }

                // 来自SDK的事件
                else if (msg.what == HandlerConstants.HANDLER_NEW_DEVICE_DISCOVERED) {
                    @SuppressWarnings("unchecked")
                    ArrayAdapter<String> adapter = (ArrayAdapter<String>) CacheControl.GetInstance().get(CacheControl.Key_AvailableSensor);
                    Sensor sensor = (Sensor) msg.obj;
                    String fullname = StringUtil.concat(sensor.Name, "[", sensor.MAC, "]");
                    if (adapter.getPosition(fullname) == -1) {
                        adapter.add(fullname);
                    }
                    sendBroadcast(new Intent(SEND_BLUETOOTH_VALUE).putExtra("name", fullname));
                } else if (msg.what == HandlerConstants.HANDLER_ERROR) {
                    addLog("错误：" + (String) msg.obj);
                } else if (msg.what == HandlerConstants.HANDLER_DEVICE_DISCOVER_COMPLETED) {
                    ToastUtil.showToast(getBaseContext(), "传感器搜索结束");
                } else if (msg.what == HandlerConstants.HANDLER_DEVICE_DISCONNECT) {
                    synchronized (_lock) {
                        if (_requestor != null) {
                            _requestor.cancel();
                            _requestor = null;
                        }
                        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Running_Status, true);
                        setControlStatus(true);
                    }
                    ToastUtil.showToast(getBaseContext(), "与传感器断开了连接，测量停止，请重新开始测量");
                    addLog("信息：与传感器断开了连接，测量停止，请重新开始测量");

                } else if (msg.what == Constants.HANDLER_REWRITE_CALIBRATION_CURVE) {
                    String notice = "";
                    try {
                        refreshCalibrationNotice();
                        if (msg.arg1 == 1) //写入校准数据成功
                        {
//							synchronized (PageControl._lock) {
//								Object values = CacheControl.GetInstance().get(CacheControl.Key_Calibration_Chart);
//								if (values != null && PageControl._temp_Curve_Chart != null) {
//									CurveValuePair p = (CurveValuePair) values;
//									PageControl._temp_Curve_Chart.changeData(p.xValue, p.yValue);
//								}
//							}
                            String ble = String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Sensor_Name_Address));
                            String BLEMac = ble.substring(ble.indexOf("[") + 1, ble.indexOf("]")).replace(":", "");
//							Setting setting=new Setting();
                            String path = setting.getData_Media_Director(CommonDef.FILE_TYPE_BaseSetting);
                            String filename = BLEMac + "-temp.txt";
                            if (SystemUtil.isFileExist(path, filename)) {
                                String curve = ReceivedDataAnalysis.getTemperatureCurve(filename);
                                if (ReceivedDataAnalysis.getCalibrationCurvePiontsValue(curve)) {
                                    CurveValuePair valuePair = (CurveValuePair) CacheControl.GetInstance().get(CacheControl.Key_Calibration_Chart);
                                    synchronized (PageControl._lock) {
                                        if (PageControl._temp_Curve_Chart != null) {
                                            PageControl._temp_Curve_Chart.changeData(valuePair.xValue, valuePair.yValue);
                                        }
                                    }
                                }
                            }
                            notice = (String) msg.obj + "。已停止测量，重新开始测量将加载新校准曲线";
                        } else {
                            notice = (String) msg.obj + "。已停止测量";
                        }
//						ToastUtil.showToast(getBaseContext(), (String)msg.obj);
                    } catch (Exception e) {
                        // TODO: handle exception
                        notice = "写入过程出现异常:" + e.getMessage();
                    } finally {
                        if (_waitingDialog != null) {
                            _waitingDialog.dismiss();
                        }
                        stopBluetoothMeasurment("停止", "校准完毕，正在停止测量，请稍后……", notice, 0);

                    }

                } else if (msg.what == Constants.HANDLER_BLUETOOTH_PAUSED) {
//					new Thread() {
//						@Override
//						public void run() {
                    Log.e(TAG, "HANDLER_BLUETOOTH_PAUSED");
                    int allowdifferencevalue = CommonDef.TempuratureAllowDifferenceValue;
                    double measurementvalue = Double.parseDouble(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Value_Temperature)));//蓝牙实时测量到的温度值
                    int calibrationvalue = Integer.parseInt(String.valueOf(CacheControl.GetInstance().get(CacheControl.Key_Tempurature_Calibration_Point_Value)));//当前应校准的温度
                    if (Math.abs(measurementvalue - calibrationvalue) > allowdifferencevalue)//如果测量值和应校准值相差比较大，可能是黑体箱温度与用户想校准的温度不是一个点，给用户一个提示，是否要强行校准
                    {
                        showForceCalibrationDialog();
                    } else {
                        rewriteCurveCalibration();
                    }
//						}
//					}.start();

                } else if (msg.what == Constants.HANDLER_CALIBRATION_CURVE_ERROR) {
                    if (_waitingDialog != null) {
                        _waitingDialog.dismiss();
                    }
                    ToastUtil.showToast(getApplicationContext(), (String) msg.obj);
                    addLog((String) msg.obj);
                } else if (msg.what == Constants.HANDLER_BLUETOOTH_MEASURE_STOP) {
                    synchronized (_lock) {
                        if (_waitingDialog != null) {
                            _waitingDialog.dismiss();
                        }
                        CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Running_Status, true);
                        setControlStatus(true);
                        if (msg.arg2 == 1) {
                            writeCalibrationFile();
                        } else {
                            CacheControl.GetInstance().addOrUpdate(CacheControl.Key_Value_RPM, 0);
                            restoreTextViewValue(R.id.txt_rpm, CacheControl.Key_Value_RPM);
                            ToastUtil.showToast(getBaseContext(), (String) msg.obj);
                        }
                    }
                } else if (msg.what == Constants.HANDLER_READY_TO_REWRITE_CALIBRATION) {
                    rewriteCurveCalibration();
                } else if (msg.what == Constants.HANDLER_CHECK_CALIBRATION_CURVE) {
                    addLog((String) msg.obj);
                    ToastUtil.showToast(getBaseContext(), "曲线检测完毕，请查看日志");
                }
            } catch (Exception e) {
                LogUtil.GetInstance().append(e);
                btn_exit_Event(null);
            }
        }
    };

    private void addReceiveErrorLog(String requestType, int code) {
        String content = "错误：";
        if (code == Constants.Error_CommandUnmatch) {
            content = content + "发送接收类型不匹配(" + requestType + ")";
        } else if (code == Constants.Error_HeaderUnmatch) {
            content = content + "接收数据头不是0x7D(" + requestType + ")";
        } else if (code == Constants.Error_CRCUnmatch) {
            content = content + "CRC校验不正确(" + requestType + ")";
        } else if (code == Constants.Error_LengthUnmatch) {
            content = content + "接收长度不匹配(" + requestType + ")";
        } else if (code == Constants.Error_OtherUnmatch) {
            content = content + "其他校验错误(" + requestType + ")";
        }
        addLog(content);
    }

    @SuppressWarnings("unchecked")
    private void addLog(String log) {
        try {
//			SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
//			Date date = new Date(System.currentTimeMillis());
//			String time=" "+simpleDateFormat.format(date);

            CustomListAdapter adapter = (CustomListAdapter) CacheControl.GetInstance().get(CacheControl.Key_Log);
            synchronized (adapter) {
                if (adapter.getCount() >= 20) {
                    adapter.remove(adapter.getItem(0));
                }
//				adapter.add(time+log);
                adapter.add(log);
            }
        } catch (Exception e) {
            LogUtil.GetInstance().append(e);
            btn_exit_Event(null);
        }
    }

    private void showForceCalibrationDialog()//2016-09-12 liuhg添加
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        String strContent = "";
        strContent = "校准值与实测值相差较大，请检查黑体箱温度是否与校准值一致。是否仍要写入校准值？";
        builder.setMessage(strContent)
                .setCancelable(true)
                .setTitle("警告")
                .setPositiveButton("是", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {

                        _handler.obtainMessage(Constants.HANDLER_READY_TO_REWRITE_CALIBRATION, 0, 0, null).sendToTarget();
                    }
                })
                .setNegativeButton("否", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        dialog.cancel();
                        return;
                    }
                });
        builder.show();
    }

    /**
     * 开启广播，传输数据
     *
     * @param action intent的actiong名称
     * @param key
     * @param val
     */
    private void startSendBroadcast(String action, String key, String val) {
        Intent mIntent = new Intent();
        mIntent.setAction(action);
        mIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
        Bundle bundle = new Bundle();
        bundle.putString(key, val);
        mIntent.putExtras(bundle);
        sendBroadcast(mIntent);
    }

    @Override
    protected void onDestroy() {
        if (controlReceiver != null)
            unregisterReceiver(controlReceiver);
        if (intent != null)
            getApplicationContext().stopService(intent);    //2019-02-16 chupengyu修改，停止广播服务
        super.onDestroy();
    }
}
